SWAGOLX.EXE (c) 1993 GDSOFT ALL RIGHTS RESERVED 00010 1 08-24-9413:27ALL PAUL WEST CD-ROM Dectection SWAG9408 v6D@ 51 ╣ {π JM>Would you happen to have any example code to determine if a drive is aπ JM>hard disk, cd-rom, ramdrive etc. ?ππHere is a unit that will at least tell you a little about the CD-ROM. Not allπMSCDEX functions are implemented, but enough to identify the CD-ROMS.π}πunit CDROM;ππ{$X+} { Extended Syntax Rules }ππinterfaceππtypeπ CDR_DL_ENTRY = recordπ UNITNO : byte;π OFFSET : word;π SEGMENT : word;π end;ππ CDR_DL_BUFFER = array[1..26] of CDR_DL_ENTRY;π CDR_DRIVE_UNITS = array[0..25] of byte;π CDR_VTOC = array[1..2048] of byte;ππ{ 00h } procedure CDR_GET_DRIVE_COUNT (var COUNT, FIRST: word);π{ 01h } procedure CDR_GET_DRIVE_LIST (var LIST: CDR_DL_BUFFER);π{ 02h } function CDR_GET_COPR_NAME (DRIVE: byte): string;π{ 03h } function CDR_GET_ABSTRACT_NAME (DRIVE: byte): string;π{ 04h } function CDR_GET_BIBLIO_NAME (DRIVE: byte): string;π{ 05h Read VTOC }π{ 06h Reserved }π{ 07h Reserved }π{ 08h Absolute Disk Read }π{ 09h Absolute Disk Write }π{ 0ah Reserved }π{ 0bh } function CDR_DRIVE_CHECK (DRIVE: byte): boolean;π{ 0ch } function CDR_VERSION: word;π{ 0dh } procedure CDR_GET_DRIVE_UNITS (var BUFFER: CDR_DRIVE_UNITS);π{ 0eh Get or Set VDR }π{ 0fh Get Dir Entry }π{ 10h Send Device Request }ππimplementationππuses dos, strings;ππconstπ CDROM_INTERRUPT = $2f;ππvarπ REG : registers;ππprocedure CDR_GET_DRIVE_COUNT (var COUNT, FIRST: word);πassembler;ππ{ Returns the total number of CD-ROM Drives in the system }π{ and the logical drive number of the first drive. }ππ{ In a system that contains multiple CD-ROM Drives and is }π{ also networked, the CD-ROM drives might not be assigned }π{ as consecutive logical units. See also MSCDEX Function }π{ 0Dh (Get CD-ROM Drive Letters) }ππasmπ mov ax, 1500hπ xor bx, bxπ int CDROM_INTERRUPTπ les di, COUNTπ mov es:[di], bxπ les di, FIRSTπ mov es:[di], cxπend;ππprocedure CDR_GET_DRIVE_LIST (var LIST: CDR_DL_BUFFER);πassembler;ππ{ Returns a driver unit identifier for each CD-ROM drive }π{ in the system, along with the address of the header for }π{ the device driver that controls the drive. }ππ{ The driver unit code returned in the buffer is not the }π{ systemwide logical drive identifier but is the relative }π{ unit for that particular driver. For example if three }π{ CD-ROM drivers are installed, each supporting one phy- }π{ sical drive, the driver unit code in each 5 byte entry }π{ will be 0. The systemwide drive identifiers for each }π{ CD-ROM unit can be obtained with MSCDEX Function 0Dh }π{ (Get CD-ROM Drive Letters). }ππasmπ mov ax, 1501hπ les bx, LISTπ int CDROM_INTERRUPTπend;ππfunction CDR_GET_COPR_NAME (DRIVE: byte): string;ππ{ Returns the name of the copyright file from the volume }π{ table of contents (VTOC) of the specified CD-ROM Drive. }ππ{ CD-ROM Specs allow for a 31 character filename followed }π{ by a semicolon (;) and a 5 digit version number. }ππ{ On disks that comply with the High Sierra standard, }π{ the filename has an MS-DOS compatable (8/3) format. }ππvarπ BUFFER : array[0..38] of char;ππbeginπ REG.AX := $1502;π REG.CX := DRIVE;π REG.ES := seg(BUFFER);π REG.BX := ofs(BUFFER);π intr(CDROM_INTERRUPT, REG);π CDR_GET_COPR_NAME := strpas(BUFFER);πend;ππfunction CDR_GET_ABSTRACT_NAME (DRIVE: byte): string;ππ{ Returns the name of the abstract file from the volume }π{ table of contents (VTOC) for the specified CD-ROM drive.}ππ{ CD-ROM Specs allow for a 31 character filename followed }π{ by a semicolon (;) and a 5 digit version number. }ππ{ On disks that comply with the High Sierra standard, }π{ the filename has an MS-DOS compatable (8/3) format. }ππvarπ BUFFER : array[0..38] of char;ππbeginπ REG.AX := $1503;π REG.CX := DRIVE;π REG.ES := seg(BUFFER);π REG.BX := ofs(BUFFER);π intr(CDROM_INTERRUPT, REG);π CDR_GET_ABSTRACT_NAME := strpas(BUFFER);πend;ππfunction CDR_GET_BIBLIO_NAME (DRIVE: byte): string;ππ{ Returns the name if the bibliographic file from the }π{ volume table of contents (VTOC) for the specified drive.}ππ{ CD-ROM Specs allow for a 31 character filename followed }π{ by a semicolon (;) and a 5 digit version number. }ππ{ This function is provided for compatability with the }π{ ISO-9660 standard. A null string is returned for disks }π{ complying with the High Sierra standard. }ππvarπ BUFFER : array[0..38] of char;ππbeginπ REG.AX := $1504;π REG.CX := DRIVE;π REG.ES := seg(BUFFER);π REG.BX := ofs(BUFFER);π intr(CDROM_INTERRUPT, REG);π CDR_GET_BIBLIO_NAME := strpas(BUFFER);πend;ππfunction CDR_DRIVE_CHECK (DRIVE: byte): boolean;ππ{ Returns a code indicating whether a particular logical }π{ unit is supported by the Microsoft CD-ROM Extensions }π{ module (MSCDEX). }ππbeginπ REG.AX := $150b;π REG.BX := $0000;π REG.CX := DRIVE;π intr(CDROM_INTERRUPT, REG);π CDR_DRIVE_CHECK := (REG.AX <> $0000) and (REG.BX = $adad);πend;ππfunction CDR_VERSION: word;ππ{ Returns the version number of the Microsoft CD-ROM Extensions }ππ{ The Major Version number is returned in the High Order byte }π{ and the Minor Version Number is returned in the Lo order }π{ byte. IE if the MSCDEX Version is 2.10, this routine will }π{ return $0210. }ππbeginπ REG.AX := $150c;π REG.BX := $0000;π intr(CDROM_INTERRUPT, REG);ππ { Version 1.0 Returns 0 instead of actual Version Number }π { So we will fix it so that this routine returns 1.0 }ππ if REG.BX = 0 then beginπ CDR_VERSION := $0100;π end else beginπ CDR_VERSION := REG.BX;π end;πend;ππprocedure CDR_GET_DRIVE_UNITS(var BUFFER: CDR_DRIVE_UNITS);πassembler;ππ{ Returns a list of the systemwide logical drive identifers }π{ that are assigned to CD-ROM drives. }ππ{ Upon return the buffer contains a series of 1 byte entries. }π{ Each entry is a logical unit code assigned to a CD-ROM drive }π{ (0 = A, 1 = B, etc); the units might not be consecutive. }ππ{ The number of valid entries can be determined by MSCDEX }π{ function 00h. }ππasmπ mov ax, 150dhπ les bx, BUFFERπ int CDROM_INTERRUPTπend;ππend.π 2 08-24-9413:28ALL OLAF GREIS CD-ROM Detection SWAG9408 LDPα 6 ╣ {πQ: How do I detect, a certain drive is a CD-Rom?ππA: The foolowing function returns True if the drive is a CD-ROM.π}ππ Uses DOS;π FUNCTION Is_CDROM(Drv : Char):BOOLEAN;π VAR R : Registers;π CDR: string;π cnt: byte;π BEGINπ Is_CDROM := false;π CDR := '';π WITH R DOπ BEGINπ AX := $1500;π BX := $0000;π CX := $0000;π Intr( $2F, R );π IF BX > 0 THENπ BEGINπ FOR cnt := 0 TO (bx-1) DOπ CDR := CDR +CHAR( CL + Byte('A') + cnt );π END;π Is_CDROM := POS( upcase(Drv), CDR ) > 0π ENDπ END;π 3 08-24-9413:30ALL TURBO POWER DPMI Read/Write Sectors SWAG9408 ▀╙uv 53 ╣ {$S-,R-,V-,I-,B-,F+,O+,A-,X+}ππunit DDisk;π {-Read and write absolute sectors using DOS int $25 and $26π in protected mode under DOS or Windows. Does not support real mode.π Requires BP7 or TPW 1.5.ππ Based on the code in the OPDOS unit from Object Professional.ππ Thanks to Maynard Riley and Mark Boler for work done on this unit.ππ Notes:π The calling parameters correspond to those in OPDOS.π Drive = 0 corresponds to drive A.π Sectors are typically 512 bytes each. NumSects*SectorSize must beπ less than 64K.π Buf may be any buffer in a protected mode program. DDISKπ temporarily allocates a DOS real mode buffer, then copiesπ the result into or out of Buf.π If the function returns False, the DosError variable from theπ DOS or WINDOS unit may have a non-zero value with more informationπ about the failure.ππ Use DPMIWriteDiskSectors with caution!ππ Version 1.0 (first public release) 7/19/94ππ For more information, contact TurboPower Softwareπ CompuServe 76004,2611π }ππinterfaceππfunction DPMIReadDiskSectors(Drive : Word;π FirstSect : LongInt; NumSects : Word;π var Buf) : Boolean;π {-Read sectors using int $25}ππfunction DPMIWriteDiskSectors(Drive : Word;π FirstSect : LongInt; NumSects : Word;π var Buf) : Boolean;π {-Write sectors using int $26}ππ {====================================================================}ππimplementationππusesπ{$IFDEF DPMI}π DOS,π{$ELSE}π WinDOS,π{$ENDIF}π WinAPI;ππtypeπ DpmiRealBuf =π objectππ privateπ Bytes : LongInt;π BufBase : LongInt;ππ publicπ constructor Init(BufBytes : LongInt);π destructor Done;π function Size : LongInt;π function Segment : Word;π function Selector : Word;π function RealPtr : Pointer;π function ProtPtr : Pointer;π end;ππ DPMIRegisters =π recordπ DI : LongInt;π SI : LongInt;π BP : LongInt;π Reserved : LongInt;π BX : LongInt;π DX : LongInt;π CX : LongInt;π AX : LongInt;π Flags : Word;π ES : Word;π DS : Word;π FS : Word;π GS : Word;π IP : Word;π CS : Word;π SP : Word;π SS : Word;π end;ππ PacketPtr = ^PacketRec;π PacketRec =π recordπ StartLo : Word;π StartHi : Word;π Count : Word;π BufOfs : Word;π BufSeg : Word;π end;ππ procedure GetRealModeIntVector(IntNo : Byte; var Vector : Pointer); assembler;π asmπ mov ax,0200hπ mov bl,IntNoπ int 31hπ les di,Vectorπ mov word ptr es:[di],dxπ mov word ptr es:[di+2],cxπ end;ππ function CallFarRealModeProc(var Regs : DPMIRegisters) : Word; assembler;π asmπ mov ax,0301hπ xor bx,bxπ xor cx,cxπ les di,Regsπ int 31hπ jc @@9π xor ax,axπ@@9:π end;ππ function DpmiRealBuf.Segment : Word;π beginπ Segment := BufBase shr 16;π end;ππ function DpmiRealBuf.Selector : Word;π beginπ Selector := BufBase and $FFFF;π end;ππ function DpmiRealBuf.RealPtr : Pointer;π beginπ RealPtr := Ptr(BufBase shr 16, 0);π end;ππ function DpmiRealBuf.ProtPtr : Pointer;π beginπ ProtPtr := Ptr(BufBase and $FFFF, 0);π end;ππ function DpmiRealBuf.Size : LongInt;π beginπ Size := Bytes;π end;ππ constructor DpmiRealBuf.Init(BufBytes : LongInt);π beginπ BufBase := GlobalDosAlloc(BufBytes);π if BufBase = 0 thenπ Fail;π Bytes := BufBytes;π end;ππ destructor DpmiRealBuf.Done;π beginπ GlobalDosFree(Selector);π end;ππtypeπ DiskInfoRec =π objectπ DriveNumber : Byte;π ClustersAvailable : Word;π TotalClusters : Word;π BytesPerSector : Word;π SectorsPerCluster : Word;π constructor Init(d : Byte);π end;ππ constructor DiskInfoRec.Init(d : Byte);π varπ Ok : Boolean;π beginπ DriveNumber := d; { 0 = default ; 1 = 'A' }ππ asmπ mov dl,dπ mov ah,$36π int $21π cmp ax,$FFFFπ je @8ππ les di,Selfπ mov es:[di].SectorsPerCluster,axπ mov es:[di].ClustersAvailable,bxπ mov es:[di].BytesPerSector,cxπ mov es:[di].TotalClusters,dxπ mov al,Trueπ jmp @9ππ@8: mov al,Falseπ@9: mov Ok,alπ end;ππ if not Ok thenπ Fail;π end;ππ function DPMIReadWrite(Drive : Word;π FirstSect : LongInt; NumSects : Word;π var Buf; Vector : Byte) : Boolean;π varπ SaveInt : Pointer;π Status : Word;π BufBytes : LongInt;π DiskInfo : DiskInfoRec;π InterimBuf : DpmiRealBuf;π PacketBuf : DpmiRealBuf;π Regs : DPMIRegisters;π beginπ DosError := 0;π DPMIReadWrite := False;ππ if not DiskInfo.Init(Drive+1) thenπ Exit;ππ BufBytes := LongInt(NumSects)*DiskInfo.BytesPerSector;π if BufBytes > 65535 thenπ Exit;π if not InterimBuf.Init(BufBytes) thenπ Exit;ππ if not PacketBuf.Init(SizeOf(PacketRec)) then beginπ InterimBuf.Done;π Exit;π end;ππ if Vector = $26 thenπ Move(Buf, InterimBuf.ProtPtr^, BufBytes);ππ FillChar(Regs, SizeOf(Regs), 0);π with PacketPtr(PacketBuf.ProtPtr)^ do beginπ StartLo := FirstSect and $FFFF;π StartHi := FirstSect shr 16;π Count := NumSects;π BufOfs := 0;π BufSeg := InterimBuf.Segment;π end;ππ GetRealModeIntVector(Vector, SaveInt); { returns real mode seg:ofs }π with Regs do beginπ CX := $FFFF;π AX := Drive;π BX := 0;π DS := PacketBuf.Segment;π CS := LongInt(SaveInt) shr 16;π IP := LongInt(SaveInt) and $FFFF;π end;π Status := CallFarRealModeProc(Regs);ππ if Status = 0 thenπ if Odd(Regs.Flags) thenπ DosError := Regs.AXπ else beginπ if Vector = $25 thenπ Move(InterimBuf.ProtPtr^, Buf, BufBytes);π DPMIReadWrite := True;π end;ππ PacketBuf.Done;π InterimBuf.Done;π end;ππ function DPMIReadDiskSectors(Drive : Word;π FirstSect : LongInt; NumSects : Word;π var Buf) : Boolean;π beginπ DPMIReadDiskSectors := DPMIReadWrite(Drive, FirstSect, NumSects, Buf, $25);π end;ππ function DPMIWriteDiskSectors(Drive : Word;π FirstSect : LongInt; NumSects : Word;π var Buf) : Boolean;π beginπ DPMIWriteDiskSectors := DPMIReadWrite(Drive, FirstSect, NumSects, Buf, $26);π end;ππend.π 4 08-24-9413:31ALL MAYNARD PHILBROOK Disk-detecting routine SWAG9408 ≈╩vÿ 6 ╣ {π -=> Quoting Christian Proehl to All <=-ππ CP> Subject: Disk-detecting routines without DOS (andππ CP> Muelheim, den 20.05.94ππ CP> Hello!ππ CP> I have problem I don't know how to solve it.π CP> Perhaps someone around the world knows more, please help me!ππ use the bios callππ function $16, int $13π}ππfunction DiskChange( DriveNmber :Byte) :Boolean;πBeginπ ASmπ Mov AH, $16π Mov DL, driveNmberπ Int $13π Mov AL,AH; { use AL & AH as a Return Value }π End;πEnd;ππBeginπ If DiskChange(0) then Write(' Disk has Changed in Drive ''A'' ')π Elseπ Write(' Disk Has changed ');πend.π 5 08-24-9413:32ALL ANDREW EIGUS Drive Detection SWAG9408 ?╚û 11 ╣ {π SA> Does anyone have any idea of how I can check the system hardware andπ SA> identify available hard drives and disk drives?π}ππππconstπ { GetDriveType return values. REQUIRES DOS 3.x or greater}ππ dtError = 0; { Drive physically isn't available }π dtRemote = 1; { Remote (network) disk drive }π dtFixed = 2; { Fixed (hard) disk drive }π dtRemovable = 3; { Removable (floppy) disk drive }π dtBadVer = $FF; { Invalid DOS version (DOS 3.x required) }πππFunction GetDriveType(Drive : byte) : byte; assembler;πAsmπ MOV AH,30hπ INT 21hπ CMP AL,3π JGE @@1π MOV AL,dtBadVerπ JMP @@4π@@1:π MOV BL,Driveπ MOV AX,4409hπ INT 21hπ JNC @@2π MOV AL,dtErrorπ JMP @@5π@@2:π CMP AL,Trueπ JNE @@3π MOV AL,dtRemoteπ JMP @@5π@@3:π MOV AX,4408hπ INT 21hπ CMP AL,Trueπ JNE @@4π MOV AL,dtFixedπ JMP @@5π@@4:π MOV AL,dtRemovableπ@@5:πEnd; { GetDriveType }ππvarπ Drive : byte;π DT : byte;ππBeginπ for Drive := 1 to 25 doπ beginπ DT := GetDriveType(Drive);π if DT <> dtError thenπ beginπ Write('Drive ', Chr(Drive + 64), ': ');π case DT ofπ dtRemote: WriteLn('Network drive');π dtFixed: WriteLn('Hard disk');π dtRemovable: WriteLn('Floppy drive')π endπ endπ endπEnd.ππ 6 08-24-9417:52ALL BJÖRN FELTEN TRUENAME (BASM) SWAG9408 ∞E ò 10 ╣ {SWAG=DOS.SWG,BJÖRN FELTEN,TRUENAME (BASM)}ππ{ Updated DOS.SWG on August 24, 1994 }ππππprogram TName; { to test the TrueName function }ππfunction TrueName(var P: string): string; assembler;π{ returns TrueName just like the DOS command does }π{ if error, returns a zero length string }π{ will probably crash for DOS versions < 3.0 }π{ donated to the Public Domain by Björn Felten @ 2:203/208 }πasmπ push dsπ lds si,Pπ@strip:π inc si { skip length byte ... }π cmp byte ptr [si],' 'π jle @strip { ... and trailing white space }ππ les di,@Resultπ inc di { leave room for byte count }π mov ah,60h { undocumented DOS call }π int 21hπ pop dsπ jc @errorππ mov cx,80 { convert ASCIZ to Pascal string }π xor ax,axπ repnz scasb { find trailing zero }π mov ax,80π sub ax,cx { get length byte }π jmp @retππ@error:π xor ax,ax { return zero length string }ππ@ret:π les di,@Resultπ stosbπend;πππvar S:string;πbeginπ S:=paramstr(1);π if paramcount<>1 thenπ writeln('Usage: tname <filename>')π elseπ writeln('TrueName of ',S,' is ',TrueName(S))πend.π 7 08-24-9417:53ALL VARIOUS TrueName equivalent SWAG9408 u╧ 20 ╣ π{ This program uses a proc from my pascal library that I use to getπ true names. Written and tested with tp4 should work with any tp andπ dos 3.1+ gm 05/94 }πusesπ dos;π {--05/93 gary a. mays --}π { this procedure uses the undocumented dos function $60 to fetch theπ canonical name of a file or path specification }π procedure canonicalize(path: string; var canonical: string;π var stat: word);π varπ regs : registers;π i : integer;π bytes : byte absolute canonical;π beginπ with regs doπ beginπ stat := 0;π ah := $60;π path := path + chr(0); { convert to asciz }π ds := seg(path[1]); { asciz name }π si := ofs(path[1]);π es := seg(canonical[1]);{ points to 128 byte result buffer }π di := ofs(canonical[1]);{ result is asciz }π msdos(regs); { returns canonical name: does not have to exist... }π if flags and fcarry > 0 thenπ stat := axπ elseπ beginπ bytes := 0;π while canonical[bytes + 1] <> #0 do inc(bytes); {conv to ascii}π { not tested on a network - this test will fail on net drive }π if canonical[2] <> ':' then { bad because of bad path }π stat := 3;π end;π end;π end; {canonicalize}ππ varπ stat : word;π path : string;π canonical : string;πbeginπ if paramstr(1) = '' thenπ path := '.'π elseπ path := paramstr(1);π canonicalize(path, canonical, stat);π case stat ofπ 0: writeln(canonical);π 2: writeln('Invalid path: ',path);π 3: writeln('Invalid drive or malformed path: ',path);π else writeln('Status: ',stat,' for ',path);π end; {case}πend.πππIL> I'm looking for an equivalent to the DOS command TRUENAME. Here's anππprogram TruePath;πuses OpString,DOS;πvarπ OldName, NewName : String;π RegisterSet : Registers;πBeginπ OldName:=ParamStr(1);π OldName[Length(OldName)+1] := #0;π NewName[0] := #0;π With RegisterSet doπ Beginπ AH := $60;π AL := 0;π DS := Seg(OldName[1]);π SI := Ofs(OldName[1]);π ES := Seg(NewName[1]);π DI := Ofs(NewName[1]);π End;π MsDos(RegisterSet);π If Odd(RegisterSet.Flags) Thenπ Writeln('Failure ',RegisterSet.AX) (* failure code *)π Elseπ Beginπ NewName[0]:=#255;π NewName[0]:=Chr(Pos(#0,NewName));π Writeln(NewName);π End;πEnd.π 8 08-25-9409:06ALL MARTIN RICHARDSON Getting Disk Type SWAG9408 Iⁿû 12 ╣ {πMR│ How do you tell the difference between a fixed hard drive, and aπ │ removable drive or network drive? Why? I have a program which reportsππThis little demo program contains the answers for most of yourπquestions.πππ{ uses int $21, service $44, subservices 8 & 9 to get driveπ existence, removeable/non-removeable, and local/remote status }ππuses dos;ππvar drive : word;π ts : string[30];π r : registers;π drexist : boolean;ππbeginπ for drive := 1 to 26 doπ beginπ drexist := false;π ts := 'unkn';ππ r.ax := $4408; { check for dos floppy/hard drv }π r.bl := drive;π msdos(r);π if not odd(r.flags) then { if not carry then ... }π beginπ drexist := true;π if (r.ax = 0) then ts := 'floppy' else ts := 'hard';π end;ππ r.ax := $4409; { check for local/remote (lan) drv }π r.bl := drive;π msdos(r);π if not odd(r.flags) thenπ beginπ drexist := true;π if ((r.dh and $10) <> 0) then ts := 'remote';π end;ππ If DrExist thenπ beginπ ts := chr(ord('A')+pred(drive))+': ' + ts;π writeln(ts);π end;π end;πend.π 9 08-25-9409:11ALL GREG VIGNEAULT VOLUME LABEL Program SWAG9408 TΣ≥▀ 26 ╣ {π>Can someone please tell me how to read the volume label off a hardπ>disk or floppy. I haven't been able to find any information on howπ>to do this. Thanks for any help you can offer.ππ Here's one way, which is valid for DOS 3.0 or higher...ππ}πPROGRAM VOLAB; { Read a disk volume label (TP4+) }π { June 12, 1994. Greg Vigneault }πUSES Dos; { import MsDos, Registers }πTYPE ASCIIZ = ARRAY [0..255] OF CHAR; { ASCIIZ strings }πCONST TAB = #9; { ASCII horizontal tab }πVAR Drv : CHAR; { drive letter 'A'..'Z' }π Volume : STRING; { for volume label }π Reg : Registers; { to access CPU registers }ππPROCEDURE Asciiz2TP (AStr:ASCIIZ; VAR Temp:STRING);π { convert an ASCIIZ (DOS) string to a TP string }π VAR Index:BYTE; BEGIN Index := 0;π WHILE (Index < 255) AND (AStr[Index] <> #0) DO BEGINπ Temp[Index+1] := AStr[Index];; INC(Index);π END{WHILE};; Temp[0] := CHR(Index);π END {Asciiz2TP};ππPROCEDURE TP2Asciiz (TStr:STRING; VAR Temp:ASCIIZ);π { convert a TP string to an ASCIIZ (DOS) string }π VAR Index:BYTE; BEGIN Index := ORD(TStr[0]);; Temp[Index] := #0;π WHILE (Index > 0) DO BEGINπ Temp[Index-1] := TStr[Index];; DEC(Index);π END{WHILE};π END {TP2Asciiz};ππFUNCTION GetVolLabel (Drv:CHAR):STRING;π VAR Temp:ASCIIZ; Temp2:STRING; Index:BYTE; seg0,ofs0:WORD;π DTA : ARRAY [0..127] OF CHAR; BEGIN Temp2 := '';π IF Drv IN ['A'..'Z'] THEN BEGIN { valid drive spec? }π Reg.AH := $2F;; MsDos(Reg); { get current DTA address }π seg0 := Reg.ES;; ofs0 := Reg.BX; { save the orig DTA }π Reg.DS := SEG(DTA);; Reg.DX := OFS(DTA); { our local DTA }π Reg.AH := $1A;; MsDos(Reg); { activate our DTA }π Temp2 := '?:\*.*';; Temp2[1] := Drv; { build filespec }π TP2Asciiz (Temp2, Temp); { xlate to ASCIIZ }π Reg.DS := SEG(Temp);; Reg.DX := OFS(Temp);; Reg.CX := 8;π Reg.AH := $4E;; MsDos(Reg); { label search, then reset DTA... }π Reg.DS := seg0;; Reg.DX := ofs0;; Reg.AH := $1A;; MsDos(Reg);π IF NOT ODD(Reg.FLAGS) { no DOS error? }π THEN FOR Index := $1E TO $2A DO Temp[Index-$1E] := DTA[Index]π ELSE Temp[0] := #0; { if no volume label found }π Asciiz2TP(Temp, Temp2); { xlate DOS to TP string }π IF (Length(Temp2) > 8) AND (Temp2[9] = '.') { if 8/3 format }π THEN Delete (Temp2,9,1);π END{IF Drv};π GetVolLabel := Temp2;π END {GetVolLabel};ππBEGIN {VOLAB: here we go...}ππ WriteLn;; WriteLn (TAB,'ReadVOL v0.01 Greg Vigneault');; WriteLn;π REPEATπ Write (TAB,'Read volume label from which drive [A..Z] ? ');π Read (Drv);; Drv := UpCase(Drv);π UNTIL Drv IN ['A'..'Z'];π Volume := GetVolLabel (Drv);; WriteLn;π IF Length(Volume) <> 0π THEN WriteLn (TAB,'Volume in drive ',Drv,': is ', Volume)π ELSE WriteLn (TAB,'No label for volume in drive ',Drv,':');π WriteLn;ππEND {VOLAB}.π 10 08-25-9409:12ALL JOSE CAMPIONE Valid Drives SWAG9408 ±∞WU 12 ╣ πprogram valid_drv;ππuses dos;ππ{ πFunction ready_drives reports as valid only drives that are πready to be read. Findfirst does not cause a critical error even πif a floppy is not ready and in machines with a single floppy πthe prompt to insert a diskette when testing for the B: drive π(from IO.SYS) is avoided by the use of DOS services $4408 and π$440E (requires DOS 3.2 or up). - πJose Campione (1:163/513.3) August 1994 -π} ππfunction ready_drives: string;πvarπ regs : registers;π i : byte;π drs: string;π sr : searchrec;ππ function is_last(d:byte):boolean;π {true if d is the only or the last name assigned to that drive}π beginπ regs.ax:= $440E;π regs.bl:= d;π msdos(regs);π is_last:= ((regs.flags and fcarry) = 0) and ((regs.al = 0) or (regs.al = d));π end;ππ function is_floppy(d: byte): boolean;π {true if d is a removable medium}π beginπ regs.ax:= $4408;π regs.bl:= d;π msdos(regs);π is_floppy := ((regs.flags and fcarry) = 0) and (regs.ax = 0);π end;ππbeginπ drs:= '';π for i:= 1 to 26 do beginπ if (not is_floppy(i)) or is_last(i) then beginπ findfirst(chr(i + 64) + ':\*.*',AnyFile,sr);π if doserror = 0 then drs:= drs + chr(i + 64);π end;π end;π ready_drives:= drs;πend;ππbeginπ writeln('drives ready : ',ready_drives);πend.ππ